#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
#include <mutex>

class Tickets
{
public:
    bool GetTickets()
    {
        bool ret = true;
        _mtx.lock();//加锁
        if(_tickets > 0)
        {
            //进行抢票
            usleep(1000);//休眠1ms
            std::cout << "我是[" << pthread_self() << "], 我要抢的票是：" << _tickets << std::endl;
            _tickets--;
        }
        else 
        {
            std::cout << "票被抢完了" << std::endl;
            ret = false;
        }   
        _mtx.unlock();//解锁  
        return ret;  
    }

private:
    int _tickets = 1000;//定义100张票
    // pthread_mutex_t _mtx;//定义一把锁
    std::mutex _mtx;//C++语言封装的mutex
};

//tickets就是一份临界资源
//线程切换的时机（1：时间片到了， 2：从内核返回到用户态的时候）
void* thread_run(void* args)
{
    Tickets* t = (Tickets*)args;

    while(true)
    {
        if(!t->GetTickets())
        {
            break;
        }
    }
}

int main()
{
    pthread_t tid[5];
    Tickets* t  = new Tickets;

    for(int i = 0; i < 5; ++i)
    {
        pthread_create(tid+i, nullptr, thread_run, t);
    }

    for(int i = 0; i < 5; ++i)
    {
        pthread_join(tid[i], nullptr);
    }

    delete t;
    return 0;
}


// #include <iostream>
// #include <cstdio>
// #include <string>
// #include <ctime>
// #include <mutex>
// #include <cstdlib>
// #include <unistd.h>
// #include <pthread.h>

// // 抢票逻辑，10000票，5线程同时再抢
// //tickets是不是就是所谓的临界资源！ tickets-- 是原子的吗？(是安全的吗？)
// //为了让多个线程进行切换，线程什么时候可能切换(1. 时间片到了 2. 检测的时间点：从内核态返回用户态的时候)
// //对临界区进行加锁
// class Ticket{
//     private:
//     int tickets;
   
//     pthread_mutex_t mtx; //原生线程库,系统级别

//     public:
//     Ticket():tickets(10000)
//     {
//         pthread_mutex_init(&mtx, nullptr);
//     }
//     bool GetTicket()
//     {
//         //static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
//         //bool变量是否是被所有线程共享的呢？？不是的！
//         bool res = true;
//         //我要访问临界资源的时候tickets, 需要先访问mtx，前提是所有线程必须得先看到它！
//         //那么锁本身，是不是也是临界资源！！！！
//         //你如何保证锁本身是安全的！！！
//         //原理：lock，unlock-> 是原子的！！（为甚么？）
//         //一行代码是原子的：只有一行汇编的情况
//         pthread_mutex_lock(&mtx); 
//         //  pthread_mutex_lock(&mtx); 
//         // mymtx.lock();
//         //执行这部分代码的执行流就是互斥的，串行执行的！
//         if(tickets > 0){
//             usleep(1000); //1s == 1000ms 1ms = 1000us
//             std::cout << "我是[" << pthread_self() << "] 我要抢的票是: " << tickets << std::endl;
//             tickets--; //这里看起来就是一行C、C++代码
//             //抢票
//         }
//         else{
//             printf("票已经被抢空了\n");
//             res = false;
//         }
//         pthread_mutex_unlock(&mtx);
//         // mymtx.unlock();
//         return res;
//     }
//     ~Ticket()
//     {
//         pthread_mutex_destroy(&mtx);
//     }
// };


// void *ThreadRoutine(void *args)
// {
//     Ticket *t = (Ticket*)args;

//     //购票的时候，不能出现负数的情况
//     // srand((long)time(nullptr));
//     while(true)
//     {
//         if(!t->GetTicket())
//         {
//             break;
//         }
//     }
// }

// int main()
// {
//     Ticket *t = new Ticket();

//     pthread_t tid[5];
//     for(int i = 0; i < 5; i++){
//         int *id = new int(i);
//         pthread_create(tid+i, nullptr, ThreadRoutine, (void*)t);
//     }

//     for(int i = 0 ; i < 5; i++){
//         pthread_join(tid[i], nullptr);
//     }
//     return 0;
// }

// #include <iostream>
// #include <pthread.h>
// #include <string>
// #include <unistd.h>

// class Tickets
// {
// public:
//     Tickets()
//     {
//         pthread_mutex_init(&_mtx, nullptr);//初始化锁
//     }

//     ~Tickets()
//     {
//         pthread_mutex_destroy(&_mtx);//释放锁
//     }

//     bool GetTickets()
//     {
//         bool ret = true;
//         pthread_mutex_lock(&_mtx);//加锁
//         if(_tickets > 0)
//         {
//             //进行抢票
//             usleep(1000);//休眠1ms
//             std::cout << "我是[" << pthread_self() << "], 我要抢的票是：" << _tickets << std::endl;
//             _tickets--;
//         }
//         else 
//         {
//             std::cout << "票被抢完了" << std::endl;
//             ret = false;
//         }   
//         pthread_mutex_unlock(&_mtx);//解锁  
//         return ret;  
//     }

// private:
//     int _tickets = 1000;//定义100张票
//     pthread_mutex_t _mtx;//定义一把锁
// };

// //tickets就是一份临界资源
// //线程切换的时机（1：时间片到了， 2：从内核返回到用户态的时候）
// void* thread_run(void* args)
// {
//     Tickets* t = (Tickets*)args;

//     while(true)
//     {
//         if(!t->GetTickets())
//         {
//             break;
//         }
//     }
// }

// int main()
// {
//     pthread_t tid[5];
//     Tickets* t  = new Tickets;

//     for(int i = 0; i < 5; ++i)
//     {
//         pthread_create(tid+i, nullptr, thread_run, t);
//     }

//     for(int i = 0; i < 5; ++i)
//     {
//         pthread_join(tid[i], nullptr);
//     }

//     delete t;
//     return 0;
// }

// int tickets = 100;//定义100张票

// //tickets就是一份临界资源
// //线程切换的时机（1：时间片到了， 2：从内核返回到用户态的时候）
// void* thread_run(void* args)
// {
//     int id = *(int*)args;//获取id
//     delete (int*)args;//手动释放空间
//     while(true)
//     {
//         if(tickets > 0)
//         {
//             //进行抢票
//             usleep(1000);//休眠1ms
//             std::cout << "我是[" << id << "], 我要抢的票是：" << tickets << std::endl;
//             tickets--;
//         }
//         else 
//         {
//             //没票
//             break;
//         }
//     }
// }

// int main()
// {
//     pthread_t tid[5];
//     for(int i = 0; i < 5; ++i)
//     {
//         int* id = new int(i);//防止i在main线程被改变
//         pthread_create(tid+i, nullptr, thread_run, id);
//     }
    
//     for(int i = 0; i < 5; ++i)
//     {
//         pthread_join(tid[i], nullptr);
//     }

//     return 0;
// }

// void* thread_run(void* args)
// {
//     std::string tname = (char*)args;
//     while(true)
//     {
//         std::cout << tname << "is running..." << std::endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, thread_run, (void*)"new thread");
//     pthread_join(tid, nullptr);
//     return 0;
// }